<template>
    <ElRow :gutter="15">
        <ElCol :span="4" style="height: 70%">
            <ElCard style="height: 100%">
                <ElTree style="max-width: 600px" node-key="id" @node-click="handleTreeClick" class="tree-node"
                    :data="deptTree" :props="{ children: 'children', label: 'name' }">
                    <template #default="{ node, data }">
                        <span class="tree-node" :title="data.name">{{ data.name }}</span>
                    </template>
                </ElTree>
            </ElCard>
        </ElCol>

        <ElCol :span="20" style="position:relative;">
            <ElCard class="marginBottom">
                <ElForm inline>
                    <ElFormItem label="昵称" style="margin-bottom: 0;">
                        <ElInput v-model="searchNickName" placeholder="请输入昵称" maxlength="30" show-word-limit></ElInput>
                    </ElFormItem>
                    <ElFormItem label="用户名" style="margin-bottom: 0;">
                        <ElInput v-model="searchUsername" placeholder="请输入用户名" maxlength="30" show-word-limit></ElInput>
                    </ElFormItem>
                    <ElFormItem label="用户状态" style="margin-bottom: 0;">
                        <ElSelectV2 v-model="searchIsDisable" clearable placeholder="请选择用户状态" style="width: 240px"
                            :options="selectOptions" />
                    </ElFormItem>
                    <ElFormItem style="margin-bottom: 0;">
                        <ElButton @click="onSearchUser" type="primary">搜索</ElButton>
                        <ElButton @click="onReset" type="primary">重置</ElButton>
                    </ElFormItem>
                </ElForm>
            </ElCard>

            <ElCard>
                <template #header>
                    <ElButton type="primary" @click="onAddUser" v-hasPermi="['sys:user:insert']">新增用户</ElButton>
                </template>
                <ElTable :data="resultData.records" v-loading="isLoading">
                    <ElTableColumn label="昵称" prop="nickName" />
                    <ElTableColumn label="用户名" prop="username" />
                    <ElTableColumn label="所属部门">
                        <template #="{ row, $index }: { row: SysUserVO, $index: number }">
                            {{ sysDeptIdToName[row.deptId] ?? row.deptId }}
                        </template>
                    </ElTableColumn>
                    <ElTableColumn label="启用状态">
                        <template #="{ row, $index }: { row: SysUserVO, $index: number }">
                            {{ row.isDisabled ? '停用' : '开启' }}
                        </template>
                    </ElTableColumn>
                    <ElTableColumn label="创建时间">
                        <template #="{ row, $index }: { row: SysUserVO, $index: number }">
                            {{ row.createTime }}
                        </template>
                    </ElTableColumn>

                    <ElTableColumn label="修改时间">
                        <template #="{ row, $index }: { row: SysUserVO, $index: number }">
                            {{ row.modifyTime }}
                        </template>
                    </ElTableColumn>

                    <ElTableColumn label="操作" width="350px">
                        <template #="{ row, $index }: { row: SysUserVO, $index: number }">
                            <ElButton type="primary" @click="onShowDetailUser(row)" v-hasPermi="['sys:user:query']">详情
                            </ElButton>
                            <ElButton type="warning" @click="onEditUser(row)" v-hasPermi="['sys:user:update']">编辑
                            </ElButton>
                            <Popconfirm :title="`确定删除${row.username}?`" icon="Delete" @confirm="onDeleteUser(row)">
                                <ElButton type="danger" v-hasPermi="['sys:user:delete']">删除</ElButton>
                            </Popconfirm>
                            <ElButton type="danger" @click="() => row.id ? handleResetPassword(row.id) : undefined"
                                v-hasPermi="['sys:user:update']">重置密码</ElButton>
                        </template>
                    </ElTableColumn>
                </ElTable>
                <template #footer>
                    <Pagination v-model="resultData" @pageInfoChange="handleQuery"></Pagination>
                </template>
            </ElCard>

            <ElDialog v-model="dialogInfo.show" :title="dialogInfo.title" width="700px" :show-close="false"
                :close-on-press-escape="false" :close-on-click-modal="false">
                <ElForm ref="formInstance" :rules="checkFormRoles" :model="formInfo" label-width="auto"
                    :disabled="dialogInfo.disable">
                    <ElRow>
                        <ElCol :span="12">
                            <ElFormItem label="用户名" prop="username">
                                <ElInput v-model="formInfo.username" placeholder="请输入用户名" maxlength="16"
                                    show-word-limit />
                            </ElFormItem>
                        </ElCol>
                        <ElCol :span="12">
                            <ElFormItem v-if="!formInfo.id" label="密码" prop="password">
                                <ElInput v-model="formInfo.password" type="password" placeholder="请输入密码" maxlength="16"
                                    show-word-limit show-password />
                            </ElFormItem>
                        </ElCol>
                    </ElRow>
                    <ElRow>
                        <ElCol :span="12">
                            <ElFormItem label="昵称" prop="nickName">
                                <ElInput v-model="formInfo.nickName" placeholder="请输入昵称" maxlength="16"
                                    show-word-limit />
                            </ElFormItem>
                        </ElCol>
                        <ElCol :span="12">
                            <ElFormItem label="所属部门" prop="deptId">
                                <DeptSelect v-model:dept-id="formInfo.deptId" />
                            </ElFormItem>
                        </ElCol>
                    </ElRow>
                    <ElRow>
                        <ElCol :span="12">
                            <ElFormItem label="用户角色" prop="roleIds">
                                <ElSelectV2 style="width: 100%" v-model="formInfo.roleIds" :options="roleList"
                                    placeholder="请选择角色" multiple />
                            </ElFormItem>
                        </ElCol>
                        <ElCol :span="12">
                            <ElFormItem prop="isDisabled" label="是否启用">
                                <ElSwitch v-model="formInfo.isDisabled" :active-value="0" :inactive-value="1" />
                            </ElFormItem>
                        </ElCol>
                    </ElRow>
                </ElForm>
                <template #footer>
                    <ElButton @click="hideDialog">取消</ElButton>
                    <ElButton type="primary" @click="submitFormData()">确认</ElButton>
                </template>
            </ElDialog>
        </ElCol>
    </ElRow>
</template>

<script setup lang="ts">
import { onBeforeMount, onBeforeUpdate, reactive, ref } from "vue";
import { ElButton, ElCard, ElCol, ElDialog, ElForm, ElFormItem, ElInput, ElMessageBox, ElRow, ElSelectV2, ElSwitch, ElTable, ElTableColumn, ElTree, type FormRules } from "element-plus";
import { queryDeptAll } from "@/api/sysDept/sysDept";
import type { SysDeptVO } from "@/api/sysDept/sysDeptType";
import { type SysUserDTO, type SysUserFiltDTO, type SysUserVO } from "@/api/sysUser/sysUserType";
import Popconfirm from "@/components/custom/Popconfirm.vue";
import { usePageQuery } from "@/hook/useQuery";
import { addUser, deleteUser, queryUser, queryUserPage, resetUserPassword, updateUser } from "@/api/sysUser/sysUser";
import { useFormDialog } from "@/hook/useDialog";
import DeptSelect from "../components/DeptSelect.vue";
import { queryRolePage } from "@/api/sysRole/sysRole";
import { ROLE_TYPE_SUPER_ADMIN } from "@/common";

/**
 * 部门树形结构
 */
const deptTree = ref<SysDeptVO[]>()
/**
 * 供下拉框使用的角色列表
 */
const roleList = ref<{
    label: string
    value: string
}[]>([])
/**
 * 搜索筛选部门id
 */
const searchDeptId = ref<string>()
/**
 * 搜索筛选昵称
 */
const searchNickName = ref<string>()
/**
 * 搜索筛选用户名
 */
const searchUsername = ref<string>()
/**
 * 搜索筛选状态
 */
const searchIsDisable = ref<number>()
/**
 * 搜索筛选状态的下拉选项
 */
const selectOptions = [
    {
        label: "启用",
        value: 0
    },
    {
        label: "停用",
        value: 1
    }
]
/**
 * 所有部门信息的id与name映射
 */
let sysDeptIdToName: Record<string, string>

/**
 * 部门树形结构被点击时调用
 * @param node 
 */
const handleTreeClick = async (node: SysDeptVO) => {
    searchDeptId.value = node.id
    onSearchUser()
}

/**
 * 新增用户
 */
const onAddUser = () => {
    initRoleList()
    showDialog('新增用户', { isDisabled: 0 } as SysUserDTO, () => addUser(formInfo.value))
}

/**
 * 修改用户
 * @param sysUserVO 要修改的用户
 */
const onEditUser = (sysUserVO: SysUserVO) => {
    initRoleList()
    showDialog('编辑用户', queryUser({ id: sysUserVO.id }), () => updateUser({ id: sysUserVO.id }, formInfo.value))
}

/**
 * 删除用户
 * @param sysUserVO 要删除的用户
 */
const onDeleteUser = async (sysUserVO: SysUserVO) => {
    await deleteUser({ id: sysUserVO.id })
    handleQuery()
}

/**
 * 用户详情
 * @param sysUserVO 要展示的用户
 */
const onShowDetailUser = async (sysUserVO: SysUserVO) => {
    initRoleList()
    showDialog('用户详情', queryUser({ id: sysUserVO.id }))
}

/**
 * 封装查询方法
 */
const {
    handleQuery, // 封装后的查询方法
    handleParamChange,
    resultData, // 查询到的数据
    isLoading   // 是否正在查询
} = usePageQuery<SysUserFiltDTO, SysUserVO>(queryUserPage)

/**
 * 根据搜索条件搜索
 */
const onSearchUser = () => {
    handleParamChange({
        nickName: searchNickName.value,
        username: searchUsername.value,
        topDeptId: searchDeptId.value,
        isDisabled: searchIsDisable.value
    })
    handleQuery()
}

/**
 * 重置搜索条件
 */
const onReset = () => {
    searchNickName.value = undefined
    searchUsername.value = undefined
    searchDeptId.value = undefined
    searchIsDisable.value = undefined
    onSearchUser()
}

/**
 * 用户 新增/编辑/详情 对话框相关内容
 */
const {
    showDialog,
    hideDialog,
    submitFormData,
    dialogInfo,
    formInfo,
    formInstance
} = useFormDialog<SysUserDTO>(() => handleQuery())

/**
 * 对话框校验规则
 */
const checkFormRoles = reactive<FormRules<SysUserDTO>>({
    username: [
        { required: true, message: "请输入用户名", trigger: 'blur' },
        { min: 6, max: 16, message: '用户名长度为6 - 16', trigger: 'blur' }
    ],
    nickName: [
        { required: true, message: "请输入用户昵称", trigger: 'blur' },
        { min: 2, max: 16, message: '用户昵称长度为2 - 16', trigger: 'blur' }
    ],
    deptId: [
        { required: true, message: '请选择部门', trigger: 'blur' },
    ],
    password: [
        { required: true, message: "请输入用户密码", trigger: 'blur' },
        { min: 6, max: 16, message: '用户密码长度为6 - 16', trigger: 'blur' }
    ],
    roleIds: { required: true, message: "请选择用户角色", trigger: "blur" }
})

/**
 * 加载部门信息
 */
const loadDeptData = async () => {
    const sysDeptVOArrayOfList = await queryDeptAll(true)
    sysDeptIdToName = sysDeptVOArrayOfList.reduce((sysDeptIdToName, current) => {
        if (current.id) {
            sysDeptIdToName[current.id] = current.name;
        }
        return sysDeptIdToName;
    }, {} as Record<string, string>);

    deptTree.value = await queryDeptAll()
}

/**
 * 挂载前加载部门信息
 */
onBeforeMount(() => loadDeptData())

/**
 * 更新前加载部门信息
 */
onBeforeUpdate(() => loadDeptData())

const initRoleList = async () => {
    if (roleList.value.length === 0) {
        roleList.value = (await queryRolePage({ pageNum: 1, pageSize: 99999 })).records
            .filter(item => item.type != ROLE_TYPE_SUPER_ADMIN)
            .map(item => {
                return {
                    label: item.name,
                    value: item.id ?? ''
                }
            })
    }
}

/**
 * 重置密码
 */
const handleResetPassword = (userId: string) => {
    ElMessageBox.confirm(
        "确认重置密码?",
        "警告",
        {
            type: "warning"
        }
    ).then(() => {
        return resetUserPassword({ id: userId })
    })
}
</script>

<style scoped lang="scss">
.tree-node {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
</style>
